﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spotless.Data;
using Spotless.Data.DataAccess.Interfaces;

namespace Spotless.Services
{
    public class QueryService
    {
        public QueryService()
            : this(null)
        {
        }

        public QueryService(IQueryRepository queryRepository)
        {
            this.QueryRepository = queryRepository ?? new Spotless.Data.DataAccess.Sql.QueryRepository();
        }

        protected virtual IQueryRepository QueryRepository { get; private set; }

        public List<Category> GetCategories()
        {
            return QueryRepository.Category_GetAll().ToList();
        }

        public List<DrillDown> GetTopLevelDrillDown(int categoryId, byte typeId)
        {
            return QueryRepository.DrillDown_GetTopLevelByCategoryId(categoryId, typeId).ToList();
        }

        public List<DrillDown> GetTopLevelDrillDown(int categoryId, DrillDown.DrillDownTypes type)
        {
            return QueryRepository.DrillDown_GetTopLevelByCategoryId(categoryId, (byte)type).ToList();
        }

        public List<DrillDown> GetDrillDownsByParentId(int id)
        {
            return QueryRepository.DrillDown_GetAllByParentId(id).ToList();
        }

        public List<DrillDown> GetDrillDownsByParentId(int id, DrillDown.DrillDownTypes type)
        {
            return QueryRepository.DrillDown_GetAllByParentId(id, (byte)type).ToList();
        }

        public DrillDown GetDrillDownById(int id)
        {
            return QueryRepository.DrillDown_GetById(id);
        }

        public Query CreateQuery()
        {
            var query = new Query();
            QueryRepository.AddQuery(query);
            return query;
        }

        public IQueryable<Query> GetAllQueries()
        {
            return QueryRepository.Query_GetAll();
        }

        
        public IQueryable<Query> GetOpenQueries(Dictionary<FilterExpression<Query>, string> filters)
        {
            var tmp = QueryRepository.Query_GetOpen();
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    tmp = filter.Key.Filter(tmp, filter.Value);
                }
            }
            return tmp;
        }
        public PagedList<Query> GetOpenQueries(Dictionary<FilterExpression<Query>, string> filters, string sort, int page, int pageSize)
        {
            var tmp = GetOpenQueries(filters);
            if (sort != null)
            {
                var sortExpression = SortExpression<Query>.Parse(sort);
                tmp = sortExpression.Sort(tmp);
            }
            return tmp.ToPagedList(page, pageSize);
        }

        
        public PagedList<Query> GetCompletedQueries(Dictionary<FilterExpression<Query>, string> filters, string sort, int page, int pageSize)
        {
            
            var tmp = QueryRepository.Query_GetCompleted();
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    tmp = filter.Key.Filter(tmp, filter.Value);
                }
            }
            if (sort != null)
            {
                var sortExpression = SortExpression<Query>.Parse(sort);
                tmp = sortExpression.Sort(tmp);
            }
            return tmp.ToPagedList(page, pageSize);
        }

        public IQueryable<Query> GetCompletedQueries(Dictionary<FilterExpression<Query>, string> filters)
        {
            var tmp = QueryRepository.Query_GetCompleted();
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    tmp = filter.Key.Filter(tmp, filter.Value);
                }
            }
            return tmp;
        }

        public PagedList<Query> GetOpenApprovedCompensation(Dictionary<FilterExpression<Query>, string> filters, string sort, int page, int pageSize)
        {

            var tmp = QueryRepository.Query_GetOpenApprovedCompensation();
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    tmp = filter.Key.Filter(tmp, filter.Value);
                }
            }
            if (sort != null)
            {
                var sortExpression = SortExpression<Query>.Parse(sort);
                tmp = sortExpression.Sort(tmp);
            }
            return tmp.ToPagedList(page, pageSize);
        }


        public IQueryable<Query> GetOpenApprovedCompensation(Dictionary<FilterExpression<Query>, string> filters)
        {

            var tmp = QueryRepository.Query_GetOpenApprovedCompensation();
            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    tmp = filter.Key.Filter(tmp, filter.Value);
                }
            }
            
            return tmp;
        }

        public PagedList<Query> GetOpenDeclinedCompensation(Dictionary<FilterExpression<Query>, string> filters, string sort, int page, int pageSize)
        {

        var tmp = QueryRepository.Query_GetOpenDeclinedCompensation();
        if (filters != null)
        {
            foreach (var filter in filters)
            {
                tmp = filter.Key.Filter(tmp, filter.Value);
            }
        }
        if (sort != null)
        {
            var sortExpression = SortExpression<Query>.Parse(sort);
            tmp = sortExpression.Sort(tmp);
        }
        return tmp.ToPagedList(page, pageSize);


    }

        public int countQueries()
        {
            return QueryRepository.Query_CountAll();
        }

        public IQueryable<Query> CompletedQueries_GetRange(DateTime? from, DateTime? to)
        {
            var tmp = QueryRepository.Query_GetCompleted();
            if (from.HasValue)
                tmp = tmp.Where(x => x.Updated >= from.Value.Date);
            if(to.HasValue)
                tmp = tmp.Where(x => x.Updated <= to.Value.Date.AddDays(1).AddMilliseconds(-1));
            return tmp;

        }

        public int CompletedQueries_GetCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Count();
        }

        public int CompletedQueries_GetEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x=> x.QueryTypeId==2).Count();
        }

        //website
        public int CompletedQueries_GetWebsiteEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x=> x.QueryTypeId==2 && x.SourceId==1 ).Count();
        }
        public int CompletedQueries_GetWebsiteComplaintCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x=> x.QueryTypeId==3 && x.SourceId==1 ).Count();
        }
        public float CompletedQueries_GetWebsiteTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 1).Sum(x => x.Amount) ?? 0;
        }
        //Email
        public int CompletedQueries_GetEmailEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 2 && x.SourceId == 2).Count();
        }
        public int CompletedQueries_GetEmailComplaintCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 2).Count();
        }
        public float CompletedQueries_GetEmailTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 2).Sum(x => x.Amount) ?? 0;
        }

        //Telephone
        public int CompletedQueries_GetTelephoneEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 2 && x.SourceId == 3).Count();
        }
        public int CompletedQueries_GetTelephoneComplaintCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 3).Count();
        }
        public float CompletedQueries_GetTelephoneTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 3).Sum(x => x.Amount) ?? 0;
        }

        //Letter
        public int CompletedQueries_GetLetterEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 2 && x.SourceId == 4).Count();
        }
        public int CompletedQueries_GetLetterComplaintCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 4).Count();
        }
        public float CompletedQueries_GetLetterTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId== 4).Sum(x => x.Amount) ?? 0;
        }

        //Retailer
        public int CompletedQueries_GetRetailerEnquiryCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 2 && x.SourceId == 5).Count();
        }
        public int CompletedQueries_GetRetailerComplaintCount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 5).Count();
        }
        public float CompletedQueries_GetRetailerTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Where(x => x.QueryTypeId == 3 && x.SourceId == 5).Sum(x => x.Amount) ?? 0;
        }



        
        public float CompletedQueries_GetTotalAmount(DateTime? from, DateTime? to)
        {
            return CompletedQueries_GetRange(from, to).Sum(x => x.Amount) ?? 0;
        }






        public List<Query> GetPendingCompensation()
        {
            return QueryRepository.Query_GetPendingCompensation().ToList();
        }

        public IQueryable<Query> GetPendingCompensationForUser(System.Security.Principal.IIdentity user, Dictionary<FilterExpression<Query>, string> filters, string sort)
        {
            if (user != null)
            {
                var tmp = QueryRepository.Query_GetPendingCompensationForUser(user.Name);
                if (filters != null)
                {
                    foreach (var filter in filters)
                    {
                        tmp = filter.Key.Filter(tmp, filter.Value);
                    }
                }
                if (sort != null)
                {
                    var sortExpression = SortExpression<Query>.Parse(sort);
                    tmp = sortExpression.Sort(tmp);
                }
                return tmp;
            }

            else
            {
                return null;
            }

        }

        public PagedList<Query> GetPendingCompensationForUser(System.Security.Principal.IIdentity user, Dictionary<FilterExpression<Query>, string> filters, string sort, int page, int pageSize)
        {
            return GetPendingCompensationForUser(user, filters, sort).ToPagedList(page, pageSize);
        }

        
        //get id
        //public List<Query> GetQuery()
           public Query GetById(int id)
           {
               return QueryRepository.Query_GetById(id);
            }

        public void ApproveCompensation(int id)
        {
            QueryRepository.Query_ApproveCompensation(id);
        }

        //
        public void SaveChanges()
        {
            QueryRepository.SaveChanges();
        }

        public Category GetCategoryById(int categoryId)
        {
            return QueryRepository.Category_GetById(categoryId);
        }

        public List<DetailedReport> GetDetailedReport(DateTime? from, DateTime? to, int[] categoryIDs, int[] productIDs)
        {
            return QueryRepository.DetailedReport_Search(from, to, categoryIDs, productIDs).ToList();
        }

        public List<ComplaintsAlert> ComplaintAlert_GetAllForUser(System.Security.Principal.IPrincipal iPrincipal)
        {
            return QueryRepository.ComplaintsAlert_GetAllFormUser(iPrincipal.Identity.Name).ToList();
        }

        public aspnet_User User_GetByLoggedIn(System.Security.Principal.IPrincipal iPrincipal)
        {
            return QueryRepository.AspNetUser_GetByName(iPrincipal.Identity.Name);
        }

        public void Insert(ComplaintsAlert item)
        {
            QueryRepository.AddComplaintsAlert(item);
        }

        public void Delete(ComplaintsAlert item)
        {
            QueryRepository.DeleteComplaintsAlert(item);
            
        }
    }
}
